/**
 * @file    hnjd_rs485.c
 * @brief   汇能精电-通信协议
 * @author  Liuwei
 * @version 1.0.1
 * @date    2023-11-30
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-11-30 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "hnjd_rs485.h"
#include "modbus_app.h"
#include "if_di.h"
#include "cfg_prj.h"
#include "sample.h"
#include "parallel_com.h"
#include "var_mng.h"
#include "param_mng.h"
#include "diagnosis.h"
/* macro/define --------------------------------------------------------------*/

/* typedef -------------------------------------------------------------------*/
#define CMD_READ_IN          (0x04)
#define CMD_READ_COIL        (0x01)
#define CMD_WRITE_COIL       (0x05)
#define CMD_READ_HOLD        (0x03)
#define CMD_WRITE_HOLD       (0x10)

#define IN1_REG_ST           (0x3100)
#define IN1_REG_END          (0x3200) 
#define IN1_REG_SIZE         (IN1_REG_END - IN1_REG_ST + 1)

#define HOLD_REG_ST          (0x9000)
#define HOLD_REG_END         (0x9100) 
#define HOLD_REG_SIZE        (HOLD_REG_END - HOLD_REG_ST + 1)

#define COIL_REG_ST          (0x00)
#define COIL_REG_END         (0x08) 
#define COIL_REG_SIZE        (COIL_REG_END - COIL_REG_ST + 1)

/* local functions -----------------------------------------------------------*/
static void hnjd_read_input_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void hnjd_update_input_buf(void);
static void hnjd_read_hold_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void hnjd_update_hold_buf(void);
static void hnjd_write_hold_buf(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void hnjd_read_coil_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static void hnjd_update_coil_buf(void);
static void hnjd_write_coil_buf(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len);
static uint16_t get_ouv_state(void);
static uint16_t get_cc_state(void);
static uint16_t get_ct_state(void);
static uint16_t get_et_state(void);
static uint16_t get_mt_state(void);
static uint16_t get_batt_state(void);
static uint16_t get_mos_state(void);
/* static variables ----------------------------------------------------------*/
static uint16_t input_reg_buf[IN1_REG_SIZE] = {0};
static uint16_t hold_reg_buf[HOLD_REG_SIZE] = {0};
static uint16_t coil_reg_buf[COIL_REG_SIZE/8] = {0};
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
uint8_t hnjd_rs485_analysis(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len)
{
    md_data_type recv_md_data = {0};
    if(TRUE == modbus_rtu_analysis(rx_buf , rx_len , &recv_md_data))
    {
        if((recv_md_data.addr == 4)||(recv_md_data.addr == 1)) // 协议要求固定地址为4
        {
            if(CMD_READ_IN == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= IN1_REG_ST)
                    && (recv_md_data.reg_addr + recv_md_data.data_len <= IN1_REG_END))
                {
                    hnjd_update_input_buf();
                    hnjd_read_input_reg(recv_md_data , tx_buf , tx_len);
                    return TRUE;
                }
            }
            else if(CMD_READ_HOLD == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= HOLD_REG_ST)
                    && (recv_md_data.reg_addr + recv_md_data.data_len <= HOLD_REG_END))
                {
                    hnjd_update_hold_buf();
                    hnjd_read_hold_reg(recv_md_data , tx_buf , tx_len);
                    return TRUE;
                }
            }
            else if(CMD_WRITE_HOLD == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= HOLD_REG_ST)
                    && (recv_md_data.reg_addr + recv_md_data.data_len <= HOLD_REG_END))
                {
                    hnjd_write_hold_buf(recv_md_data , tx_buf , tx_len);
                    return TRUE;
                }
            }
            else if(CMD_READ_COIL == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= COIL_REG_ST)
                    && (recv_md_data.reg_addr + recv_md_data.data_len <= COIL_REG_END))
                {
                    hnjd_update_coil_buf();
                    hnjd_read_coil_reg(recv_md_data, tx_buf ,tx_len);
                    return TRUE;
                }
            }
            else if(CMD_WRITE_COIL == recv_md_data.cmd_code)
            {
                if((recv_md_data.reg_addr >= COIL_REG_ST)
                    && (recv_md_data.reg_addr + recv_md_data.data_len <= COIL_REG_END))
                {
                    hnjd_write_coil_buf(recv_md_data, tx_buf ,tx_len);
                    return TRUE;
                }
            }
            else
            {

            }
        }
        return FALSE;
    }
    return FALSE;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static void hnjd_read_input_reg(md_data_type md_data_msg, uint8_t *tx_buf, uint16_t *tx_len) 
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;
    uint16_t st_addr = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    data_len = md_data_msg.data_len * 2;
    p_tx[idx_cnt ++] = data_len;
    
    st_addr = md_data_msg.reg_addr - IN1_REG_ST;
    for (i = 0; i < md_data_msg.data_len; ++i) 
	{
        p_tx[idx_cnt ++] = input_reg_buf[i + st_addr] >> 8;
		p_tx[idx_cnt ++] = input_reg_buf[i + st_addr];
    }

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}

static void hnjd_update_input_buf(void)
{

    uint8_t i = 0;
    uint32_t u32_val = 0;
    uint32_t v32_val = 0;
	
    input_reg_buf[0] = param_get_data(PAR_ID_CB_CELL_NUM);
    input_reg_buf[1] = master_data_reg.avg_batt_volt;
    input_reg_buf[2] = master_data_reg.total_bus_curr;
    v32_val = master_data_reg.total_bus_curr * master_data_reg.avg_batt_volt * 0.01;
	input_reg_buf[3] = v32_val & 0xff;
    input_reg_buf[4] = v32_val >> 16;
    input_reg_buf[5] = master_data_reg.total_full_cap * 0.01;
    input_reg_buf[6] = master_data_reg.avg_soc;

    if(master_data_reg.total_bus_curr == 0)
        u32_val = 0xffff;
    else
        u32_val = master_data_reg.total_full_cap * master_data_reg.avg_soc / master_data_reg.total_bus_curr * 0.01 * 60;
    input_reg_buf[7] = u32_val;
    input_reg_buf[8] = (master_data_reg.max_temp_val - 2731) * 10;
    input_reg_buf[9] = (master_data_reg.min_temp_val - 2731) * 10;
    input_reg_buf[10] = (var_get_data(VAR_ID_ENV_TEMP) - 500) * 10;
    input_reg_buf[11] = (var_get_data(VAR_ID_ENV_TEMP) - 500) * 10;
    input_reg_buf[12] = (var_get_data(VAR_ID_MOS_TEMP) - 500) * 10;
    input_reg_buf[13] = master_data_reg.avg_cycle;
    input_reg_buf[14] = 0;

    input_reg_buf[15] = get_ouv_state();
    input_reg_buf[16] = get_cc_state();

    input_reg_buf[17] = get_mos_state();
    input_reg_buf[18] = get_ct_state();
    input_reg_buf[19] = get_et_state();
    input_reg_buf[20] = get_mt_state();

    for(i = 0;i < 16; ++ i)
    {
        input_reg_buf[21 + i] = 0;
    }
    input_reg_buf[38] = 0;
    input_reg_buf[39] = get_batt_state();
    input_reg_buf[40] = 0;
    input_reg_buf[41] = 0;
    input_reg_buf[42] = 0;
    input_reg_buf[43] = 0;
    input_reg_buf[44] = 0;
    input_reg_buf[45] = 0;
    input_reg_buf[46] = 0;
    input_reg_buf[47] = 0;
    input_reg_buf[48] = 0;
}

static void hnjd_read_hold_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;
    uint16_t st_addr = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    data_len = md_data_msg.data_len * 2;
    p_tx[idx_cnt ++] = data_len;
    
    st_addr = md_data_msg.reg_addr - HOLD_REG_ST;
    for (i = 0; i < md_data_msg.data_len; ++i) 
	{
        p_tx[idx_cnt ++] = hold_reg_buf[i + st_addr] >> 8;
		p_tx[idx_cnt ++] = hold_reg_buf[i + st_addr];
    }

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}

static void hnjd_update_hold_buf(void)
{
    hold_reg_buf[0] = param_get_data(PAR_ID_CUV_ALM_VAL);
    hold_reg_buf[1] = var_get_data(VAR_ID_TP_SOP_DV) * 10;
    hold_reg_buf[2] = var_get_data(VAR_ID_TP_SOP_CV) * 10;
    hold_reg_buf[3] = param_get_data(PAR_ID_BOV_PRP_VAL);
    hold_reg_buf[4] = param_get_data(PAR_ID_OCC_ALM_VAL) * 10;
    hold_reg_buf[5] = var_get_data(VAR_ID_SOP_CC) * 10;
    hold_reg_buf[6] = param_get_data(PAR_ID_OCD1_ALM_VAL) * 10;
    hold_reg_buf[7] = var_get_data(VAR_ID_SOP_DC) * 10;
    hold_reg_buf[8] = (param_get_data(PAR_ID_OTC_PRP_VAL) - 500) * 10;
    hold_reg_buf[9] = (param_get_data(PAR_ID_UTC_PRP_VAL) - 500) * 10;
    hold_reg_buf[10] = (param_get_data(PAR_ID_OTD_PRP_VAL) - 500) * 10;
    hold_reg_buf[11] = (param_get_data(PAR_ID_UTD_PRP_VAL) - 500) * 10;
    hold_reg_buf[12] = (param_get_data(PAR_ID_OTD_PRP_VAL) - 500) * 10;
    hold_reg_buf[13] = (param_get_data(PAR_ID_UTD_PRP_VAL) - 500) * 10;
    hold_reg_buf[14] = (param_get_data(PAR_ID_OTE_ALM_VAL) - 500) * 10;
    hold_reg_buf[15] = (param_get_data(PAR_ID_UTE_ALM_VAL) - 500) * 10;
    hold_reg_buf[16] = (param_get_data(PAR_ID_OTE_ALM_VAL) - 500) * 10;
    hold_reg_buf[17] = (param_get_data(PAR_ID_UTE_ALM_VAL) - 500) * 10;
    hold_reg_buf[18] = (param_get_data(PAR_ID_OTM_ALM_VAL) - 500) * 10;
    hold_reg_buf[19] = 0;
    hold_reg_buf[20] = 10;
    hold_reg_buf[21] = 0;
    hold_reg_buf[22] = 0;
    hold_reg_buf[23] = 0;
    hold_reg_buf[20] = 0;
}

static void hnjd_write_hold_buf(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{

    uint16_t crc_code = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    p_tx[idx_cnt ++] = md_data_msg.reg_addr >> 8; 
    p_tx[idx_cnt ++] = md_data_msg.reg_addr & 0xff;
    p_tx[idx_cnt ++] = md_data_msg.data_len >> 8; 
    p_tx[idx_cnt ++] = md_data_msg.data_len & 0xff;

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}

static void hnjd_read_coil_reg(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint16_t data_len = 0;
    uint16_t crc_code = 0;
    uint8_t i = 0;
    uint8_t *p_tx = tx_buf;
	uint16_t idx_cnt = 0;
    uint16_t st_addr = 0;

    p_tx[idx_cnt ++] = md_data_msg.addr;
    p_tx[idx_cnt ++] = md_data_msg.cmd_code;
    data_len = (md_data_msg.data_len + 7) / 8;
    p_tx[idx_cnt ++] = data_len;
    
    st_addr = md_data_msg.reg_addr - COIL_REG_ST;
    for (i = 0; i < data_len; ++i) 
	{
        p_tx[idx_cnt ++] = coil_reg_buf[i + st_addr];
    }

    crc_code = modbus_calc_crc(tx_buf, idx_cnt);

    p_tx[idx_cnt ++] = crc_code & 0xff;
    p_tx[idx_cnt ++] = crc_code >> 8;

    *tx_len = idx_cnt;   //修改
}

static void hnjd_update_coil_buf(void)
{
    coil_reg_buf[0] = 0;
}

static void hnjd_write_coil_buf(md_data_type md_data_msg , uint8_t *tx_buf ,uint16_t *tx_len)
{
    uint8_t coil_data = 0;
    coil_data = md_data_msg.data_buf[0];

    if(coil_data & (1 << 0)) // 回复出厂默认参数
    {
//		 param_valid_check(PARAM_RESET);
//         param_save_all();

    }

    if(coil_data & (1 << 2)) // 清除内部故障
    {

    }

    if(coil_data & (1 << 0)) // 重启
    {

    }
}

static uint16_t get_ouv_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_alarm(ALM_ID_CUV) || diag_get_alarm(ALM_ID_BUV))
		state |= 0x01;
	if(diag_get_alarm(ALM_ID_COV) || diag_get_alarm(ALM_ID_BUV))
		state |= 0x02;
	if(diag_get_prp(PRP_ID_CUV) || diag_get_prp(PRP_ID_BUV))
		state |= 0xF1;
	if(diag_get_prp(PRP_ID_COV) || diag_get_prp(PRP_ID_BUV))
		state |= 0xF2;
	
	return state;
}

static uint16_t get_cc_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_alarm(ALM_ID_OCD))
		state |= 0x01;
	if(diag_get_alarm(ALM_ID_OCC))
		state |= 0x02;
	if(diag_get_prp(PRP_ID_OCD) || diag_get_prp(PRP_ID_OCD2))
		state |= 0xF1;
	if(diag_get_prp(PRP_ID_OCC))
		state |= 0xF2;
	
	return state;
}

static uint16_t get_ct_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_alarm(ALM_ID_UTC))
		state |= 0x01;
	if(diag_get_alarm(ALM_ID_OTC))
		state |= 0x02;
	if(diag_get_prp(PRP_ID_TOL))
		state |= 0xF0;
	if(diag_get_prp(PRP_ID_UTC) || diag_get_prp(PRP_ID_UTD))
		state |= 0xF1;
	if(diag_get_prp(PRP_ID_OTC) || diag_get_prp(PRP_ID_OTD))
		state |= 0xF2;
	
	return state;
}

static uint16_t get_mos_state(void)
{
	uint16_t state = 0;
	
	if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_CHG))
		state |= 0x01;
	if(var_get_data(VAR_ID_MOS_STATE) & (1 << VAR_MOS_ST_DSG))
		state |= 0x02;

	return state;	
}

static uint16_t get_et_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_alarm(ALM_ID_UTE))
		state |= 0x01;
	if(diag_get_alarm(ALM_ID_OTE))
		state |= 0x02;
	if(diag_get_prp(PRP_ID_UTE))
		state |= 0xF1;
	if(diag_get_prp(PRP_ID_OTE))
		state |= 0xF2;
	
	return state;
}

static uint16_t get_mt_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_alarm(ALM_ID_OTM))
		state |= 0x02;

	if(diag_get_prp(PRP_ID_OTM))
		state |= 0xF2;
	
	return state;
}

static uint16_t get_batt_state(void)
{
	uint16_t state = 0;
	
	if(diag_get_prp(PRP_ID_BOV) || diag_get_prp(PRP_ID_COV) || diag_get_prp(PRP_ID_OCC)
		|| diag_get_prp(PRP_ID_OTC) || diag_get_prp(PRP_ID_OTD) || diag_get_prp(PRP_ID_OCC2))
		state |= (1 << 0);
	if(diag_get_prp(PRP_ID_BUV) || diag_get_prp(PRP_ID_CUV) || diag_get_prp(PRP_ID_OCD)
		||diag_get_prp(PRP_ID_OTD) || diag_get_prp(PRP_ID_UTD) || diag_get_prp(PRP_ID_OCD2) || diag_get_prp(PRP_ID_SC))
		state |= (1 << 1);
	if(diag_get_prp(PRP_ID_VDIFF) || diag_get_prp(PRP_ID_COL) || diag_get_prp(PRP_ID_TOL)
		||diag_get_prp(PRP_ID_OTE) || diag_get_prp(PRP_ID_OTE) || diag_get_prp(PRP_ID_OTM))
		state |= (1 << 2);
	if(diag_get_prp(PRP_ID_OTC) || diag_get_prp(PRP_ID_UTC))
		state |= (1 << 3);
	if(diag_get_prp(PRP_ID_OTD) || diag_get_prp(PRP_ID_UTD))
		state |= (1 << 4);
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1))
		state |= (1 << 12);	
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_FROCE_CHG1))
		state |= (1 << 13);
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_DSG_EN) == FALSE)
		state |= (1 << 14);
	if(parallel_get_pcs_ctrl(PARALLEL_PCS_CHG_EN) == FALSE)
		state |= (1 << 15);
	
	return state;
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/
